package com.zhj.common.advice;


import com.zhj.common.base.Result;
import com.zhj.common.util.CharPool;
import com.zhj.common.util.JsonUtils;
import com.zhj.common.util.StringUtils;

import org.springframework.core.MethodParameter;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * rest controller的切面增强，只切对应包下面的controller否则knife文档生成会出问题
 */
@RestControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalResultAdvice implements ResponseBodyAdvice<Object> {


    /**
     * Supports
     *
     * @param methodParameter method parameter
     * @param aClass          a class
     * @return the boolean
     * @since 1.0.0
     */
    @Override
    public boolean supports(MethodParameter methodParameter,
                            Class<? extends HttpMessageConverter<?>> aClass) {
        String name = methodParameter.getDeclaringClass().getPackage().getName();
        if (StringUtils.isBlank(name)) {
            return false;
        }
        String currentPackage = this.getClass().getPackage().getName();
        //获取到当前应用包名的前面两个名称例如：com.zhj.package 获取到 com.zhj
        currentPackage = StringUtils.subStringBeforeNthOccurrence(currentPackage, CharPool.DOT, 2);
        return name.startsWith(currentPackage);
    }

    /**
     * Before body write
     *
     * @param body               o
     * @param methodParameter    method parameter
     * @param mediaType          media type
     * @param aClass             a class
     * @param serverHttpRequest  server http request
     * @param serverHttpResponse server http response
     * @return the object
     * @since 1.0.0
     */
    @Override
    public Object beforeBodyWrite(Object body,
                                  MethodParameter methodParameter,
                                  MediaType mediaType,
                                  Class<? extends HttpMessageConverter<?>> aClass,
                                  ServerHttpRequest serverHttpRequest,
                                  ServerHttpResponse serverHttpResponse) {
        return this.warp(body);
    }

    /**
     * Warp
     *
     * @param body body
     * @return the object
     * @since 1.0.0
     */
    private Object warp(Object body) {
        if (body instanceof Result) {
            return body;
        }
        Result<Object> result = Result.success(body);
        if (body instanceof String) {
            return JsonUtils.toJson(result);
        }
        return result;
    }
}
